﻿/*************************************************************************************
 * 文 件 名:   HK_TagAndLayerView
 * 
 * 描    述:   场景中Tag和Layer的管理工具，对项目中所有的Tag标签及Layer层级进行显示，显示当前场景中对应Tag标签（或Layer层级）包含的物体数量，且可进行选择。
 * 
 * 版    本：  V1.0
 * 创 建 者：  京产肠饭
 * 创建时间：  2023/8/5
 * 链   接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using QFramework;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace HKTools
{
    public class HK_TagAndLayerView : EditorWindow
    {
        const int TagAndLayerViewPriority = 24;

        bool isShowTagView = true;
        bool isShowLayerView = false;

        static string[] tagNames;
        static int[] tagNums;

        static List<string> layerNames;
        static List<int> layerNums;

        [MenuItem("HKTools/TagAndLayerView(标签与层级预览工具)", priority = TagAndLayerViewPriority)]
        static void Init()
        {
            GetWindow<HK_TagAndLayerView>().Show();

            RefreshTags();
            RefreshLayers();
        }

        void OnGUI()
        {
            EditorGUILayout.Space();

            EditorGUILayout.BeginHorizontal();

            //GUILayout.FlexibleSpace();

            if (GUILayout.Toggle(isShowTagView, "显示场景中的Tag", "Toggle"))
            {
                RefreshTags();
                isShowTagView = true;
                isShowLayerView = false;
            }

            if (GUILayout.Toggle(isShowLayerView, "显示场景中的Layer", "Toggle"))
            {
                RefreshLayers();
                isShowTagView = false;
                isShowLayerView = true;
            }

            //GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 2), new Color(0.5f, 0.5f, 0.5f, 1));

            if (isShowTagView)
            {
                ShowTagViewDraw();
            }

            if (isShowLayerView)
            {
                ShowwLayerViewDraw();
            }
        }

        void ShowTagViewDraw()
        {
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("当前场景中Tag的赋值情况:", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            EditorGUILayout.BeginHorizontal(GUILayout.Width(340));
            {
                EditorGUILayout.LabelField("Tag标签名:", EditorStyles.boldLabel, GUILayout.Width(120));
                EditorGUILayout.LabelField("Tag标签包含数量:", EditorStyles.boldLabel, GUILayout.Width(140));
                EditorGUILayout.LabelField("选择:", EditorStyles.boldLabel, GUILayout.Width(60));
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(0.5f);

            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), new Color(0.5f, 0.5f, 0.5f, 1));

            EditorGUILayout.Space(0.5f);

            for (int i = 0; i < tagNames.Length; i++)
            {
                if (tagNames[i] == "Untagged")
                    continue;

                EditorGUILayout.BeginHorizontal(GUILayout.Width(340));
                {
                    EditorGUILayout.LabelField(tagNames[i], GUILayout.Width(120));
                    EditorGUILayout.LabelField(tagNums[i].ToString() + " 个物体", GUILayout.Width(140));

                    if (GUILayout.Button("Select", GUILayout.Width(60)))
                    {
                        List<Object> obj_List = new List<Object>();

                        Scene currentScene = SceneManager.GetActiveScene();
                        GameObject[] rootGos = currentScene.GetRootGameObjects();

                        foreach (GameObject rootObject in rootGos)
                        {
                            Transform[] tfArray = rootObject.GetComponentsInChildren<Transform>(true);

                            foreach (Transform tf in tfArray)
                            {
                                if (tf != null && tf.CompareTag(tagNames[i]))
                                {
                                    obj_List.Add(tf.gameObject);
                                }
                            }
                        }

                        Selection.objects = obj_List.ToArray();
                    }
                }
                EditorGUILayout.EndHorizontal();
            }

            EditorGUILayout.Space(3);

            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 2), new Color(0.5f, 0.5f, 0.5f, 1));

            EditorGUILayout.Space(3);

            GUILayout.BeginHorizontal(GUILayout.Width(330));
            {
                GUILayout.FlexibleSpace();

                if (GUILayout.Button("刷新", GUILayout.Width(100)))
                {
                    RefreshTags();
                }
            }
            GUILayout.EndHorizontal();
        }

        void ShowwLayerViewDraw()
        {
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("当前场景中Layer的赋值情况:", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            EditorGUILayout.BeginHorizontal(GUILayout.Width(340));
            {
                EditorGUILayout.LabelField("Layer层级名:", EditorStyles.boldLabel, GUILayout.Width(120));
                EditorGUILayout.LabelField("Layer层级包含数量:", EditorStyles.boldLabel, GUILayout.Width(140));
                EditorGUILayout.LabelField("选择:", EditorStyles.boldLabel, GUILayout.Width(60));
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(0.5f);

            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), new Color(0.5f, 0.5f, 0.5f, 1));

            EditorGUILayout.Space(0.5f);

            for (int i = 0; i < layerNames.Count; i++)
            {
                if (layerNames[i] == "Default")
                    continue;

                EditorGUILayout.BeginHorizontal(GUILayout.Width(340));
                {
                    EditorGUILayout.LabelField(layerNames[i], GUILayout.Width(120));
                    EditorGUILayout.LabelField(layerNums[i].ToString() + " 个物体", GUILayout.Width(140));

                    if (GUILayout.Button("Select", GUILayout.Width(60)))
                    {
                        List<Object> obj_List = new List<Object>();

                        Scene currentScene = SceneManager.GetActiveScene();
                        GameObject[] rootGos = currentScene.GetRootGameObjects();

                        foreach (GameObject rootObject in rootGos)
                        {
                            Transform[] tfArray = rootObject.GetComponentsInChildren<Transform>(true);

                            foreach (Transform tf in tfArray)
                            {
                                if (tf != null && tf.gameObject.IsInLayerMask(LayerMask.GetMask(layerNames[i])))
                                {
                                    obj_List.Add(tf.gameObject);
                                }
                            }
                        }

                        Selection.objects = obj_List.ToArray();
                    }
                }
                EditorGUILayout.EndHorizontal();
            }

            EditorGUILayout.Space(3);

            EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 2), new Color(0.5f, 0.5f, 0.5f, 1));

            EditorGUILayout.Space(3);

            GUILayout.BeginHorizontal(GUILayout.Width(330));
            {
                GUILayout.FlexibleSpace();

                if (GUILayout.Button("刷新", GUILayout.Width(100)))
                {
                    RefreshLayers();
                }
            }
            GUILayout.EndHorizontal();
        }

        // 刷新 Tag 标签
        static void RefreshTags()
        {
            tagNames = UnityEditorInternal.InternalEditorUtility.tags;
            tagNums = new int[tagNames.Length];

            for (int i = 0; i < tagNames.Length; i++)
            {
                Scene currentScene = SceneManager.GetActiveScene();
                GameObject[] rootGos = currentScene.GetRootGameObjects();

                foreach (GameObject rootGo in rootGos)
                {
                    Transform[] tfArray = rootGo.GetComponentsInChildren<Transform>(true);

                    foreach (Transform tf in tfArray)
                    {
                        if (tf != null && tf.CompareTag(tagNames[i]))
                        {
                            tagNums[i]++;
                        }
                    }
                }
            }
        }

        // 刷新 Layer 层级
        static void RefreshLayers()
        {
            layerNames = new List<string>();
            layerNums = new List<int>();

            int index = 0;

            for (int i = 0; i < 32; i++)
            {
                string layerName = LayerMask.LayerToName(i);

                if (!string.IsNullOrEmpty(layerName))
                {
                    layerNames.Add(layerName);
                    layerNums.Add(0);

                    Scene currentScene = SceneManager.GetActiveScene();
                    GameObject[] rootGos = currentScene.GetRootGameObjects();

                    foreach (GameObject rootGo in rootGos)
                    {
                        Transform[] tfArray = rootGo.GetComponentsInChildren<Transform>(true);

                        foreach (Transform tf in tfArray)
                        {
                            if (tf != null && tf.gameObject.IsInLayerMask(LayerMask.GetMask(layerName)))
                            {
                                layerNums[index]++;
                            }
                        }
                    }

                    index++;
                }
            }
        }
    }
}